package com.zq.it.cms.common.shiro;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;

import com.zq.it.cms.common.security.CredentialsDigest;
import com.zq.it.cms.common.security.CredentialsMatcherAdapter;
import com.zq.it.cms.common.security.UnactivatedAccountException;
import com.zq.it.cms.common.util.Encodes;
import com.zq.it.cms.domain.User;
import com.zq.it.cms.service.UserService;

public class ShiroDbRealm extends AuthorizingRealm implements InitializingBean{

	@Autowired
	private UserService userService;
	@Autowired
	private CredentialsDigest credentialsDigest;
	
	@Override
	public void afterPropertiesSet() throws Exception {
		setCredentialsMatcher(new CredentialsMatcherAdapter(credentialsDigest));
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();
		User user = (User)principals.getPrimaryPrincipal();
		user = userService.findById(user.getId());
		
		auth.addStringPermission("*");
		return auth;
	}
	
	/**
	 * 认证回调函数,登录时调用.
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken)authcToken;
		User user = userService.findByUserName(token.getUsername());
		if(user != null){
			if(user.isActive() && !user.isLocked()){
				String salt = user.getSalt();
				byte[] salts = null;
				if (StringUtils.isNotBlank(salt)) {
					salts = Encodes.decodeHex(salt);
				}
				return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(salts), getName());
			}else if(user.isLocked()){
				throw new LockedAccountException();
			}else if(!user.isActive()){
				throw new UnactivatedAccountException();
			}
		}
		return null;
	}

}
